Flush kernel's TCP buffer with `MSG_MORE`-flagged packets

Posted by timn on Stack Overflow See other posts from Stack Overflow or by timn
Published on 2010-03-30T19:11:45Z Indexed on 2010/03/30 19:13 UTC
Read the original article Hit count: 468

Filed under:
|
|
|

send()'s man page reveals the MSG_MORE flag which is asserted to act like TCP_CORK. I have a wrapper function around send():

int SocketConnection_Write(SocketConnection *this, void *buf, int len) {
    errno = 0;

    int sent = send(this->fd, buf, len, MSG_NOSIGNAL);

    if (errno == EPIPE || errno == ENOTCONN) {
        throw(exc, &SocketConnection_NotConnectedException);
    } else if (errno == ECONNRESET) {
        throw(exc, &SocketConnection_ConnectionResetException);
    } else if (sent != len) {
        throw(exc, &SocketConnection_LengthMismatchException);
    }

    return sent;
}

Assuming I want to use the kernel buffer, I could go with TCP_CORK, enable whenever it is necessary and then disable it to flush the buffer. But on the other hand, thereby the need for an additional system call arises. Thus, the usage of MSG_MORE seems more appropriate to me. I'd simply change the above send() line to:

int sent = send(this->fd, buf, len, MSG_NOSIGNAL | MSG_MORE);

According to lwm.net, packets will be flushed automatically if they are large enough:

If an application sets that option on a socket, the kernel will not send out short packets. Instead, it will wait until enough data has shown up to fill a maximum-size packet, then send it. When TCP_CORK is turned off, any remaining data will go out on the wire.

But this section only refers to TCP_CORK. Now, what is the proper way to flush MSG_MORE packets?

I can only think of two possibilities:

  1. Call send() with an empty buffer and without MSG_MORE being set
  2. Re-apply the TCP_CORK option as described on this page

Unfortunately the whole topic is very poorly documented and I couldn't find much on the Internet.

I am also wondering how to check that everything works as expected? Obviously running the server through strace' is not an option. So the only simplest way would be to usenetcat' and then look at its `strace' output? Or will the kernel handle traffic differently transmitted over a loopback interface?

© Stack Overflow or respective owner

Related posts about c

    Related posts about tcp